/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.entity.BuildingContractPlus;
import org.springblade.modules.admin.entity.ElevatorContract;
import org.springblade.modules.admin.entity.ElevatorEffected;
import org.springblade.modules.admin.service.IBuildingContractPlusService;
import org.springblade.modules.admin.service.IElevatorContractService;
import org.springblade.modules.admin.vo.ElevatorEffectedVO;
import org.springblade.modules.admin.mapper.ElevatorEffectedMapper;
import org.springblade.modules.admin.service.IElevatorEffectedService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 有效电梯表 服务实现类
 *
 * @author ysq
 * @since 2022-10-13
 */
@Service
//@AllArgsConstructor
public class ElevatorEffectedServiceImpl extends BaseServiceImpl<ElevatorEffectedMapper, ElevatorEffected> implements IElevatorEffectedService {

	@Lazy
	@Autowired
	private IBuildingContractPlusService buildingContractPlusService;
	@Lazy
	@Autowired
	private IElevatorContractService elevatorContractService;

	@Override
	public IPage<ElevatorEffectedVO> selectElevatorEffectedPage(IPage<ElevatorEffectedVO> page, ElevatorEffectedVO elevatorEffected) {
		return page.setRecords(baseMapper.selectElevatorEffectedPage(page, elevatorEffected));
	}

	@Override
	public void dataEffectedElevator() {
		List<Long> contractIds = buildingContractPlusService.list(Wrappers.<BuildingContractPlus>lambdaQuery()
			.eq(BuildingContractPlus :: getStatus, 2)
			.eq(BuildingContractPlus :: getContractStatus, 2)
			.ge(BuildingContractPlus :: getContractEndTime, DateUtil.parse("2022-04-01", "yyyy-MM-dd")))
			.stream().map(t -> t.getId()).collect(Collectors.toList());
		if (Func.isEmpty(contractIds)) {
			return;
		}

		Map<Date, TreeSet<ElevatorEffected>> data = new HashMap<>(8);
		List<ElevatorContract> list = elevatorContractService.list(Wrappers.<ElevatorContract>lambdaQuery().in(ElevatorContract :: getContractId, contractIds));
		// 根据合同开始时间月份分组
		Map<Date, List<ElevatorContract>> map = list.stream().collect(Collectors.groupingBy(t -> DateUtil.beginOfMonth(t.getContractBeginTime())));
		// 补数据开始时间
		Date dataStart = DateUtil.parse("2022-04-01", "yyyy-MM-dd");
		// 补数据结束时间
		Date dataEnd = DateUtil.parse("2022-10-01", "yyyy-MM-dd");
		map.forEach((k, v) -> {
			List<ElevatorContract> itemList = v;
			for (ElevatorContract elevatorContract : itemList) {
				Date contractStart = DateUtil.beginOfMonth(elevatorContract.getContractBeginTime());
				Date contractEnd = DateUtil.beginOfMonth(elevatorContract.getContractEndTime());
				while (DateUtil.compare(contractStart, dataStart) < 0) {
					contractStart = DateUtil.offsetMonth(contractStart, 1);
				}

				while (DateUtil.compare(contractStart, contractEnd) <= 0 && DateUtil.compare(contractStart, dataEnd) <= 0) {
					TreeSet<ElevatorEffected> treeSet = data.get(contractStart);
					if (Func.isEmpty(treeSet)) {
						// 初始化数据
						treeSet = new TreeSet<>(Comparator.comparing(ElevatorEffected :: getElevatorId));
						data.put(contractStart, treeSet);
					}

					ElevatorEffected elevatorEffected = new ElevatorEffected();
					elevatorEffected.setElevatorId(elevatorContract.getElevatorId());
					elevatorEffected.setBuildingId(elevatorContract.getBuildingId());
					elevatorEffected.setContractId(elevatorContract.getContractId());
					elevatorEffected.setTenantId(elevatorContract.getTenantId());
					elevatorEffected.setRecordDate(contractStart);
					treeSet.add(elevatorEffected);
					// 下个月
					contractStart = DateUtil.offsetMonth(contractStart, 1);
				}
			}
		});

		// 插入有效梯
		data.forEach((k, v) -> {
			this.saveBatch(v);
		});
	}

	@Override
	public void effectedElevatorJob(Date date) {
		List<Long> contractIds = buildingContractPlusService.list(Wrappers.<BuildingContractPlus>lambdaQuery()
			.eq(BuildingContractPlus :: getStatus, 2)
			.eq(BuildingContractPlus :: getContractStatus, 2)
			.le(BuildingContractPlus :: getContractBeginTime, date)
			.ge(BuildingContractPlus :: getContractEndTime, date))
			.stream().map(t -> t.getId()).collect(Collectors.toList());
		if (Func.isEmpty(contractIds)) {
			return;
		}

		List<ElevatorEffected> data = new ArrayList<>();
		List<ElevatorContract> list = elevatorContractService.list(Wrappers.<ElevatorContract>lambdaQuery().in(ElevatorContract :: getContractId, contractIds));
		Map<Long, List<ElevatorContract>> map = list.stream().collect(Collectors.groupingBy(t -> t.getElevatorId()));
		map.forEach((k, v) -> {
			ElevatorContract elevatorContract = v.get(0);
			ElevatorEffected elevatorEffected = new ElevatorEffected();
			elevatorEffected.setElevatorId(elevatorContract.getElevatorId());
			elevatorEffected.setBuildingId(elevatorContract.getBuildingId());
			elevatorEffected.setContractId(elevatorContract.getContractId());
			elevatorEffected.setTenantId(elevatorContract.getTenantId());
			elevatorEffected.setRecordDate(date);
			data.add(elevatorEffected);
		});

		this.saveBatch(data);
	}

	@Override
	public List<ElevatorEffected> listAll() {
		return baseMapper.listAll();
	}

	@Override
	public List<Map<String,Object>> listAllELevatorCount() {
		return baseMapper.listAllElevatorCount();
	}

}
